/*------------------------------------------------------------------------------------------------\
| Horrible X-Wing game by Steven Haber
| st_haber@hotmail.com
|
| Entity.cpp: contains the entity class, which is a base class for the player and enemy classes
|	(also in this file)
\------------------------------------------------------------------------------------------------*/

#include "Entity.h"


//Builds an entity
Entity::Entity()
{
	//Layzar array, as many can fit onscreen
	for(int i = 0; i < NUMBERLAYZARS; i++)
		mLayzars[i] = NULL;
}


//Cleans up any resources left over
Entity::~Entity()
{
	for(int i = 0; i < NUMBERLAYZARS; i++)
	{
		if(mLayzars[i] != NULL)
			delete *(mLayzars+i);
	}
	if(mCraft != NULL)
		delete mCraft;
}


//Checks the entity's layzars against an input rectangle
int Entity::collisionCheck(Craft *craft)
{
	Layzar *check;
	int counter = 0;
	
	//For each layzar
	for(int i = 0; i < NUMBERLAYZARS; i++)
	{
		check = mLayzars[i];

		//Basically, is it inside the rectangle
		if(check != NULL && check->getCollisionX() >= craft->getLeft() && check->getCollisionX() <= craft->getLeft() + craft->getWidth()
			&& check->getCollisionY() >= craft->getTop() && check->getCollisionY() <= craft->getTop() + craft->getHeight())
		{
			counter++;
			delete *(mLayzars+i);
			mLayzars[i] = NULL;
		}
	}

	//Counter is the cumulative total of collisions detected for the specified rectangle
	return counter * LAYZARDAMAGE;
}


//Draws the layzars, going through the full array and deleting the obsolete ones
void Entity::drawLayzars(float delta)
{
	for(int i = 0; i < NUMBERLAYZARS; i++)
	{
		if(mLayzars[i] != NULL)
		{
			if(!mLayzars[i]->drawLayzar(delta))
			{
				delete *(mLayzars+i);
				mLayzars[i] = NULL;
			}
		}
	}
}


//Draws the new position and sets the velocities back to 0
void Entity::draw()
{
	mCraft -> drawCraft();
	mCraft -> alterCraftX((float)0);
	mCraft -> alterCraftY((float)0);
}


//Constructor with millions of parameters: number, craft sprite, layzar offset, render window pointer, health sprites, and layzar sprites
Player::Player(int playerNumber, sf::Sprite *sprites[], int offsetX, int offsetY, sf::RenderWindow *out, Sound *sounds)
{
	//Private members initialized
	mPlayerNumber = playerNumber;
	mOut = out;
	mLayzarSprite = *sprites[LAYZAR_R];
	mLayzarOffsetX = offsetX;
	mLayzarOffsetY = offsetY;
	mSounds = sounds;
	
	mTimer.Reset();	

	//Distinguishes between players' starting positions
	sf::Sprite craft = *sprites[XWING];
	sf::Sprite health = *sprites[HEALTH_U];
	
	if(mPlayerNumber == 1)
	{
		mCraft = new Craft(*sprites[XWING], SCREENX/2 - craft.GetWidth()/2 + INITIALSHIPSPACINGX, SCREENY - 2*craft.GetHeight(), mOut, mSounds);
		mHealth = new Health(sprites, mOut, SCREENX - (int)health.GetWidth() - 20, 20, mSounds);
		mScore = new Score(mOut, 20);
		mScore->setLeft(SCREENX - (int)health.GetWidth() - 40 - mScore->getWidth());
	}
	else
	{
		mCraft = new Craft(*sprites[XWING_BLUE], SCREENX/2 - craft.GetWidth()/2 - INITIALSHIPSPACINGX, SCREENY - 2*craft.GetHeight(), mOut, mSounds);
		mHealth = new Health(sprites, mOut, 20, 20, mSounds);
		mScore = new Score(mOut, 20);
		mScore->setLeft((int)health.GetWidth() + 40);
	}
}


//Processes player input based on player number
void Player::input(float delta)
{
	if(mPlayerNumber == 1)
	{
		if(mOut -> GetInput().IsKeyDown(sf::Key::Down))
			mCraft -> alterCraftY(CRAFTVELOCITY * delta);
		if(mOut -> GetInput().IsKeyDown(sf::Key::Up))
			mCraft -> alterCraftY(-CRAFTVELOCITY * delta);
		if(mOut -> GetInput().IsKeyDown(sf::Key::Right))
			mCraft -> alterCraftX(CRAFTVELOCITY * delta);
		if(mOut -> GetInput().IsKeyDown(sf::Key::Left))
			mCraft -> alterCraftX(-CRAFTVELOCITY * delta);
		if(mOut->GetInput().IsKeyDown(sf::Key::Space) && mTimer.GetElapsedTime() >= LAYZARSPACING)
		{
			mTimer.Reset();	//The timer keeps them spaced out nicely
			newLayzar();
		}
	}

	else
	{
		if(mOut -> GetInput().IsKeyDown(sf::Key::S))
			mCraft -> alterCraftY(CRAFTVELOCITY * delta);
		if(mOut -> GetInput().IsKeyDown(sf::Key::W))
			mCraft -> alterCraftY(-CRAFTVELOCITY * delta);
		if(mOut -> GetInput().IsKeyDown(sf::Key::D))
			mCraft -> alterCraftX(CRAFTVELOCITY * delta);
		if(mOut -> GetInput().IsKeyDown(sf::Key::A))
			mCraft -> alterCraftX(-CRAFTVELOCITY * delta);
		if(mOut->GetInput().IsKeyDown(sf::Key::Tab) && mTimer.GetElapsedTime() >= LAYZARSPACING)
		{
			mTimer.Reset();
			newLayzar();
		}
	}
}


//Draws health... duh
void Player::drawHealth()
{
	mHealth -> drawHealth();
}


//Creates a new layzar in the layzar array
void Player::newLayzar()
{
	//Finds a blank space
	int i = 0;
	while(i < NUMBERLAYZARS && mLayzars[i] != NULL)
		i++;

	//New layzar
	mLayzars[i] = new Layzar(mCraft->getLeft() + mLayzarOffsetX, mCraft->getTop() + mLayzarOffsetY, true, mLayzarSprite, mOut);

	//Finds another blank space
	i = 0;
	while(i < NUMBERLAYZARS && mLayzars[i] != NULL)
		i++;

	//New layzar again
	mLayzars[i] = new Layzar(mCraft->getLeft() + mCraft->getWidth() - mLayzarOffsetX, mCraft->getTop() + mLayzarOffsetY, true, mLayzarSprite, mOut);

	if(mPlayerNumber == 1)
		mSounds->playSound(LAYZAR_ONE);
	else
		mSounds->playSound(LAYZAR_TWO);
}


//Craft getter
Craft *Player::getCraft()
{
	return mCraft;
}


//Hurter... calls the hurter inside health
bool Player::hurt(int amount)
{
	return mHealth->hurt(amount);
}


//When the player runs out of health, this happens
void Player::die()
{
	mCraft->die();
}


//Draws the score for the player
void Player::drawScore()
{
	mScore->drawScore();
}


//Scores
void Player::score(int value)
{
	mScore->addToScore(value);
}

//Constructor with millions of parameters: number, craft sprite, layzar offset, render window pointer, health sprites, and layzar sprites
Enemy::Enemy(sf::Sprite *craftSprite, int offsetX, int offsetY, sf::RenderWindow *out, sf::Sprite *layzarSprite, float initialX, int maxHealth, Sound *sounds)
{
	//Private members initialized
	mOut = out;
	mLayzarSprite = *layzarSprite;
	mLayzarOffsetX = offsetX;
	mLayzarOffsetY = offsetY;
	mHealth = maxHealth;
	mDying = false;
	mDead = false;
	mSounds = sounds;

	mTimer.Reset();	

	mCraft = new Craft(*craftSprite, initialX, 0, mOut, mSounds);
}


//Processes AI input
void Enemy::input(float delta, bool up, bool down, bool left, bool right, bool fire)
{
	if(mDying && mLayzars[0] == NULL)
		mDead = true;

	else if(!mDead && !mDying)
	{
		if(down)
			mCraft -> alterCraftY(ENEMYVELOCITY * delta);
		if(up)
			mCraft -> alterCraftY(-ENEMYVELOCITY * delta);
		if(right)
			mCraft -> alterCraftX(ENEMYVELOCITY * delta);
		if(left)
			mCraft -> alterCraftX(-ENEMYVELOCITY * delta);
		if(fire && mTimer.GetElapsedTime() >= LAYZARSPACING)
		{
			mTimer.Reset();	//The timer keeps them spaced out nicely
			newLayzar();
		}
	}
}


//Creates a new layzar in the layzar array
void Enemy::newLayzar()
{
	//Finds a blank space
	int i = 0;
	while(i < NUMBERLAYZARS && mLayzars[i] != NULL)
		i++;

	//New layzar
	mLayzars[i] = new Layzar(mCraft->getLeft() + mLayzarOffsetX, mCraft->getTop() + mCraft->getHeight() - mLayzarOffsetY, false, mLayzarSprite, mOut);

	//Finds another blank space
	i = 0;
	while(i < NUMBERLAYZARS && mLayzars[i] != NULL)
		i++;

	//New layzar again
	mLayzars[i] = new Layzar(mCraft->getLeft() + mCraft->getWidth() - mLayzarOffsetX, mCraft->getTop() + mCraft->getHeight() - mLayzarOffsetY, false, mLayzarSprite, mOut);

	mSounds->playSound(LAYZAR_ENEMY);
}


//Craft getter
Craft *Enemy::getCraft()
{
	if(!mDying && !mDead)
		return mCraft;
	return NULL;
}


//Hurter... calls the hurter inside health
bool Enemy::hurt(int amount)
{
	mSounds->playSound(HURT_ENEMY);

	mHealth -= amount;
	
	if(mHealth <= 0 && !mDying && !mDead)
		return false;
	return true;
}


//Killer
void Enemy::kill()
{
	mDying = true;
	mCraft->die();
}